package com.hichina.client.util;

import com.hichina.client.DomainInfo;
import com.hichina.exception.HiChinaException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.params.AbstractHttpParams;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: zigang.wang
 * Date: 12-3-1
 * Time: 上午10:45
 * To change this template use File | Settings | File Templates.
 */
public class HttpParam extends AbstractHttpParams {
    private Map<String, Object> parameters = new HashMap<String, Object>();
    public static final String CLIENT_ID = "client_id";
    public static final String CLIENT_SECRET = "client_secret";
    public static final String ACCESS_TOKEN = "access_token";
    public static final String UID = "uid";
    public static final String DOMAIN= "domain";
    public static final String GRANT_TYPE= "grant_type";
    public static final String SCOPE= "scope";
    public static final String REDIRECT_URI= "redirect_uri";

    public HttpParam() {
    }

    public HttpParam(String accessToken) throws HiChinaException {
        if(StringUtils.isBlank(accessToken)){
            throw new HiChinaException("accessToken required");
        }
        setAccessToken(accessToken);
    }


    public HttpParams setRedirectUri(String uri){
        setParameter(REDIRECT_URI, uri);
        return this;
    }
    
    public HttpParams setScope(String scope){
        setParameter(SCOPE, scope);
        return this;
    }
    
    public HttpParams setGrantType(String grantType){
        setParameter(GRANT_TYPE, grantType);
        return this;
    }
    
    public HttpParams setClientSecret(String secret){
        setParameter(CLIENT_SECRET, secret);
        return this;
    }
    
    public HttpParams setClientId(String clientId){
        setParameter(CLIENT_ID, clientId);
        return this;
    }

    public HttpParams setAccessToken(String accessToken){

        return setParameter(ACCESS_TOKEN, accessToken);
    }

    public Object getParameter(final String name) {
        return this.parameters.get(name);
    }
    
    public HttpParams setUid(String uid){
        return setParameter(UID, uid);
    }
    public HttpParams setDomain(String domain){
        return setParameter(DOMAIN, domain);
    }
    public HttpParams setParameter(final String name, final Object value) {
        this.parameters.put(name, value);
        return this;
    }

    public boolean removeParameter(String name) {
        //this is to avoid the case in which the key has a null value
        if (this.parameters.containsKey(name)) {
            this.parameters.remove(name);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Assigns the value to all the parameter with the given names
     *
     * @param names array of parameter names
     * @param value parameter value
     */
    public void setParameters(final String[] names, final Object value) {
        for (int i = 0; i < names.length; i++) {
            setParameter(names[i], value);
        }
    }

    /**
     * Is the parameter set?
     * <p>
     * Uses {@link #getParameter(String)} (which is overrideable) to
     * fetch the parameter value, if any.
     * <p>
     * Also @see {@link #isParameterSetLocally(String)}
     *
     * @param name parameter name
     * @return true if parameter is defined and non-null
     */
    public boolean isParameterSet(final String name) {
        return getParameter(name) != null;
    }

    /**
     * Is the parameter set in this object?
     * <p>
     * The parameter value is fetched directly.
     * <p>
     * Also @see {@link #isParameterSet(String)}
     *
     * @param name parameter name
     * @return true if parameter is defined and non-null
     */
    public boolean isParameterSetLocally(final String name) {
        return this.parameters.get(name) != null;
    }

    /**
     * Removes all parameters from this collection.
     */
    public void clear() {
        this.parameters.clear();
    }

    /**
     * Creates a copy of these parameters.
     * This implementation calls {@link #clone()}.
     *
     * @return  a new set of params holding a copy of the
     *          <i>local</i> parameters in this object.
     *
     * @deprecated
     * @throws UnsupportedOperationException if the clone() fails
     */
    public HttpParams copy() {
        try {
            return (HttpParams) clone();
        } catch (CloneNotSupportedException ex) {
            throw new UnsupportedOperationException("Cloning not supported");
        }
    }

    /**
     * Clones the instance.
     * Uses {@link #copyParams(HttpParams)} to copy the parameters.
     */
    public Object clone() throws CloneNotSupportedException {
        BasicHttpParams clone = (BasicHttpParams) super.clone();
        copyParams(clone);
        return clone;
    }

    protected void copyParams(HttpParams target) {
        Iterator iter = parameters.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry me = (Map.Entry) iter.next();
            if (me.getKey() instanceof String)
                target.setParameter((String)me.getKey(), me.getValue());
        }
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
       for (Map.Entry entry: parameters.entrySet()){
           builder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
       }
        return StringUtils.substringBeforeLast(builder.toString(), "&");
    }
}
